<!DOCTYPE html>
<html>
<head>
	<title></title>
	<meta charset="utf-8" />
	<script type="text/javascript" src="../js/jquery-1.11.3.js"></script>
	<script type="text/javascript" src="../js/utils.js"></script>
	<style type="text/css">
		.searchTip{
			/*font-style: oblique;*/
			color: rgba(128, 128, 128, 1);
		}
		.searchBox{
			border:1px solid #b6cceb;
		}
		.searchTbl{
			display: table;
			width:100%;
			background-color: white;
		}
		.searchTbl>*{
			display: table-cell;
		}
		.searchTbl input{
			width:100%;
			border:0px ;
		}
		.searchTbl>.btnSpan{
			width:16px;
			height:16px;
			padding:2px;
		}
		.searchTbl>.btnSpan>span{
			width:16px;
			height:16px;
			display:block;
			cursor: pointer;
		}
		.searchRet{
			display: none;
			position:absolute;
			z-index: 110;
		}
		.searchRet ul{
			list-style: none;
			border: 1px solid #ccc;
			margin:0;
			padding: 0;
			overflow-x: hidden;
			overflow-y: auto;
			height: 100%;
			background-color: white;
		}
		.searchRet #templeteItem{
		 	display: none;
		 }
		.searchOption{
			cursor: pointer;
			overflow: hidden;
			/*border-bottom: 1px solid #ccc;*/
			line-height: 24px;
			height:25px;	
			padding: 0 2px;
		}
		.optionHover,.optionSelected{
			background-color: #F8F8C8;	
		}
		.dropDownBtn{
 			background:url(../img/daosanjiao.jpg);
			background-size: 100% 100%; 
		}
		.searchBtn{
 			background:url(../img/search.png) no-repeat;
			background-size: 100% 100%; 
		}

	</style>
</head>

<body>
<input type="text" id="test" name="test2" placeholder="1231111" />
<input type="text" id="test" name="test2" placeholder="1231111" />
</body>
<script type="text/javascript">
/**
 * 搜索框控件
 * 调用：
 * Searchbox({
	target:''			//搜索控件对象，jQuery
	,field:'name' //搜索、显示字段
	,onSelect:''	//选中回调函数，回传选中对象
	,dataSource:[] //function or Array or Services
	,dataFilter:'' // function 回传搜索值
	,maxShowLen:8  //最大展示行数
	,delay:0.5   //搜索延迟0.5s
	,searchBtn:true  //是否显示搜索按钮
	,dropDownBtn:false // 是否带有下拉选择按钮
 * });
 * @param $
 */
;(function($){
	"use strict";
	var searchbox = function(option){
		if(!option || !option.target){
			console.log('please input search target!');
			return null;
		}
		var target = option.target;
		if( typeof target == 'string'){
			target = $('#'+target);
		}
		else if(target instanceof $){
			//jquery
		}
		else{
			target = $(target);
		}
		if(!target.length){
			return null;
		}
		var ret = [];
		target.each(function(){
			option.target = $(this);
			ret.push(new searchbox.prototype.init(option));
		});
		ret = ret.length>1 ? ret : ret[0];
		return ret;
	};
	var _isFunc = $.isFunction;
	function each(arr,fn){
		var i=0;
		var len = arr.length;
		for(;i<len; ){
			if(fn(arr[i],i++,arr) === false){
				break;
			}
		}
	};
	var keyCode ={
		13:{ //Enter
			search:false
			,keydown:function(){
				// console.log('Enter press');
				var retObj = null;
				var searchVal = this.$target.val();
				var _self = this;
				if(this.$showLi){
					if(this.pointer <0){
						this.pointer =0;
					}
					var index =this.$showLi.eq(this.pointer).prevAll().length-1;
					retObj =this.arr[index];
				}
				else{
					each(this.arr,function(o){
						if(o[_self.field] == searchVal){
							retObj = o;
							return false;
						}
					});
				}
				this.onSearchClick(searchVal,retObj);
			}
		}
		,38:{// Up
			search:false
			,keydown:function(e){
				// console.log('Up press');
				this.prev();
				e.preventDefault();
			}	
		}	
		,40:{// Down
			search:false
			,keydown:function(e){
				// console.log('Down press');
				this.next();
				e.preventDefault();
			}	
		}	
	};

	$.extend(searchbox.prototype,{
		init : function(option){
			this.option = $.extend({
				target:''			//搜索控件对象， jQuery 对象
				,field:'name' //搜索、显示字段
				,onSelect:''	//选中回调函数，回传选中对象
				,dataSource:[] //function or Array or Services
				,dataFilter:this.dataFilter // function 回传搜索值
				,maxShowLen:8  //最大展示行数
				,delay:0.5   //搜索延迟0.5s
				,searchBtn:true  //是否显示搜索按钮
				,dropDownBtn:false // 是否带有下拉选择按钮
			},option);
			this.triggerIdMap ={};
			this.$target = this.option.target;
			if(!this.option.showNames){
				this.option.showNames = this.option.field;
			}
			this.createContainer();
			if(!'placeholder' in document.createElement('input')){
				this.tip = this.$target.attr('placeholder');
			}
			this.bind();
			this.$target.blur();
		}
		,createContainer: function(){
			if(!this.option.field){
				return;
			}
			var $tar = this.$target;
			var isExist = $tar.hasClass('searchInput');
			var $sectionRet = $tar.prev('section');
			if(!isExist){
				$sectionRet = $('<section class="searchRet"></section>');
			}
			var ul = document.createElement('ul');
			var li = document.createElement('li');
			li.id= 'templeteItem';
			li.className = 'searchOption';
			ul.appendChild(li);
			$sectionRet.html(ul.outerHTML);
			if(!isExist){
				$tar.wrap('<section class="searchBox"><section class="searchTbl"><section></section></section></section>')
					.before($sectionRet).after('<div class="locator"></div>');
			}
			$tar.addClass('searchInput');
			//start to build out border
			var $searchTbl = $tar.closest('.searchTbl');
			var btnSpan = document.createElement('span');
			btnSpan.className = 'btnSpan';
			if(this.option.searchBtn && !$searchTbl.children('.searchBtn').length){
				var searchBtn = document.createElement('span');
				searchBtn.className = 'searchBtn ui-icon ui-icon-search';
				btnSpan.innerHTML = searchBtn.outerHTML;
				$searchTbl.append(btnSpan.outerHTML);

			}
			if(this.option.dropDownBtn  && !$searchTbl.children('.dropDownBtn').length){
				var dropDownBtn = document.createElement('span');
				dropDownBtn.className = 'dropDownBtn ui-icon ui-icon-carat-2-n-s';
				btnSpan.innerHTML = dropDownBtn.outerHTML;
				$searchTbl.append(btnSpan.outerHTML);
			}
		}
		,setDataSource:function(dataSource){
			this.option.dataSource = dataSource;
		}
		,refresh:function(){
			if(!this.option.field){
				return ;
			}
			if(_isFunc(this.option.dataSource)){
				this.arr = this.option.dataSource()||[];
			}
			else{
				this.arr = this.option.dataSource||[];
			}
			this.initOption();
		}
		/**
		 * 搜索选择下移
		 */
		,next:function(){
			if(!this.$showLi){
				var $section = this.$target.prev('section');
				this.$showLi = $section.find('li:visible');
				this.pointer = -1;
			}
			var len = this.$showLi.length;
			if(len>0){
				var $ul = this.$showLi.parent();
				if(this.pointer++ >= (len-1)){
					this.pointer = 0;
					$ul.scrollTop(0);
				}
				var $tarLi = this.$showLi.removeClass('optionSelected')
								.eq(this.pointer).addClass('optionSelected');
				var perliH = $('.searchOption').height();
				var maxShowLen = this.option.maxShowLen;
				var existTop = $ul.scrollTop()+maxShowLen*perliH;
				var largePointer = Math.floor(existTop/perliH)-1;
				console.log('largePointer:'+largePointer);
				console.log('this.pointer:'+this.pointer);
				if((this.pointer)>largePointer || (this.pointer + maxShowLen)<largePointer){
					$ul.scrollTop((this.pointer+1-maxShowLen)*$('.searchOption').height());
				}
				// console.log($ul.scrollTop());
				var val = $tarLi.children().text();
				this.$target.val(val);
			}
		}
		/**
		 * 搜索选择上移
		 */
		,prev:function(){
			if(!this.$showLi){
				var $section = this.$target.prev('section');
				this.$showLi = $section.find('li:visible');
				this.pointer = -1;
			}
			var len = this.$showLi.length;
			if(len>0){
				var perliH = $('.searchOption').height();
				var $ul = this.$showLi.parent();
				if(this.pointer-- <=0){
					this.pointer = len-1;
					$ul.scrollTop(this.pointer*perliH);
				}
				var $tarLi = this.$showLi.removeClass('optionSelected')
								.eq(this.pointer).addClass('optionSelected');

				var maxShowLen = this.option.maxShowLen;
				var existTop = $ul.scrollTop()+maxShowLen*perliH;
				var largePointer = Math.floor(existTop/perliH)-1;
				if((this.pointer-1)>largePointer || (this.pointer-1 + maxShowLen)<largePointer){
					$ul.scrollTop(this.pointer*perliH);
				}
				// console.log($ul.scrollTop());
				var val = $tarLi.children().text();
				this.$target.val(val);
			}
		}
		,onSearchClick:function(searchVal,selectedObj){
			var $tar = this.$target;
			if(!selectedObj){
				var $section = $tar.prev('section');
				searchVal = searchVal.trim().toLowerCase();
				var $ret = $section.find('li['+this.attrNames+'*="'+searchVal+'"]');
				if($ret.length){
					var index = $ret.eq(0).prevAll().length-1;
					selectedObj = this.arr[index];
				}
			}
			if(selectedObj){
				console.log(selectedObj[this.attrNames]);
			}
			if(_isFunc(this.option.onSelect)){
				this.option.onSelect.call(this,searchVal,selectedObj);
			}
			// $tar.prev('section').hide();
			this.reset();
		}
		,bind:function (){
			var _self = this;
			var $tar = this.$target;
			var searchVal = $tar.val();
			var showNames = this.option.showNames;
			$tar.prev('section').undelegate().delegate('li','click',function(){
				//绑定选项点击事件
				var sv = $(this).children().text();
				$tar.val(sv);
				var index = $(this).prevAll().length-1;
				_self.onSearchClick(sv,_self.arr[index]);
				$tar.focus();
			}).delegate('li','mouseover',function(){
				//绑定鼠标悬浮选项事件
				$(this).addClass('optionHover');
			}).delegate('li','mouseout',function(){
				//绑定鼠标离开选项事件
				$(this).removeClass('optionHover');
			});
			var $searchTbl = $tar.closest('.searchTbl');
			//绑定搜索按钮事件
			$searchTbl.find('.searchBtn').click(function(){
				_self.onSearchClick($tar.val());
			});
			//绑定下拉框按钮事件
			$searchTbl.find('.dropDownBtn').click(function(){
				_self.dropDownBtn();
			});
			//绑定下拉列表点击事件
			$searchTbl.find('.searchRet').mouseenter(function(){
				_self.selecting = true;
				console.log('mouseenter');
			}).mouseleave(function(){
				_self.selecting = false;
				$tar.focus();
			});
			//绑定搜索框事件
			var bindFunc ={
				keyup:function(e){
					var keySP = keyCode[e.keyCode];
					if(keySP && keySP.keyup){
						keySP.keyup.call(_self,e);
					}
					if(_self.option.field){
						if(!(keySP && keySP.search ===false)){
							_self.triggerFunc(_self.search,_self.option.delay);
						}
					}
				}
				,keydown:function(e){
//					console.log('keyCode:'+e.keyCode);
					var keySP = keyCode[e.keyCode];
					if(keySP && keySP.keydown){
						keySP.keydown.call(_self,e);
					}
				}
				,focus:function() {
					//tip function start
					if (_self.tip && $(this).hasClass('searchTip')) {
						$(this).val('');
						$(this).removeClass('searchTip');
					}
					//search function start
					if(_self.option.field){
						//加载数据
						if(!_self.arr){
							_self.refresh();
						}
					}
//					console.log('focus');
				}
				,blur:function() {
					//tip function start
					if (_self.tip && !this.value) {
						$(this).val(_self.tip);
						$(this).addClass('searchTip');
					}
					//search function start
					if(_self.option.field){
						_self.selecting ||_self.$target.prev('section').hide();
					}
//					console.log('blur');
				}
			};
			$tar.bind(bindFunc);
		}
		,dropDownBtn:function(){
			if(this.$showLi){
				this.reset();
			}
			else{
				this.search(true);	
			}
		}
		,dataFilter:function(searchVal, /*** native **/searchAll){
			var $t = this.$target;	
			var $section = $t.prev('section');
			//本地模式，筛选展示
			searchVal = searchVal.trim().toLowerCase();
			var $allLi = $section.find('li:gt(0)');
			$allLi.hide();
			this.$showLi = (searchAll || !searchVal)? $allLi:$section.find('li['+this.attrNames+'*='+searchVal+']');
		}
		/**
		 * 搜索并显示
		 */
		,search:function(searchAll){
			var $t = this.$target;	
			$t.focus();
			var $section = $t.prev('section');
			var filterArr = this.option.dataFilter.call(this,$t.val(),/** native */searchAll);
			if(filterArr){
				//服务器模式，展示所有数据
				this.arr = filterArr;
				this.initOption();
				this.$showLi = $section.find('li:gt(0)');
			}
			var maxShowLen = this.option.maxShowLen;
			var showLen = this.$showLi.length>maxShowLen ? maxShowLen :this.$showLi.length;
			//定位展示
			var tarOffset = $t.offset();
			$section.width($t.closest('.searchBox').width())
					.height(showLen*$('.searchOption').height())
					.show()
					.offset({top:$t.next('div').offset().top,left:tarOffset.left});
			this.$showLi.removeClass('optionSelected').show();
			this.pointer = -1;
		}
		,reset:function(){
			this.$target.prev('section').hide();
			this.$showLi = null;
			this.pointer = -1;
		}
		/**
		 * 延迟触发方法
		 */
		,triggerFunc:function(func,delay){
			if(_isFunc(func)){
				var _self= this;
				if(!delay){
					delay=0;
				}
				// console.log('delay:'+delay);
				for(var i in this.triggerIdMap){
					// console.log(i);
					clearTimeout(i);
				}
				this.triggerIdMap={};
				var t = setTimeout(function(){
					// console.log('call');
						func.call(_self);
					}, delay*1000);
				this.triggerIdMap[t] = true;
			}
		}
		/**
		 * 初始化搜索选项
		 * @return {[type]} [description]
		 */
		,initOption:function(){
			var $section = this.$target.prev('.searchRet');
			var $li = $section.find('#templeteItem');
			var $ul = $('<ul></ul>').append($li);
			var $liItem = $li.clone().removeAttr('id');
			var showNames = this.option.showNames;

			var field = this.option.field;
			var attrNames = field;
			if($li.attr(attrNames)){
				//与原属性冲突
				attrNames = '_'+attrNames;
			}
			this.attrNames = attrNames;
			each(this.arr,function(o){
				$liItem.html('<span class="showSpan">'+o[showNames]+'</span>');
				$liItem.attr(attrNames,(o[field]+'').trim().toLowerCase());
				$liItem.attr('title',o[showNames]);
				$ul.append($liItem[0].outerHTML);
			});
			$section.html($ul);
		}
	});
	searchbox.prototype.init.prototype = searchbox.prototype;
	window.SearchBox = searchbox;
})(jQuery);
	var sb = SearchBox({
		id:'test'
		,searchBtn:true
		,onSelect:function(val,o){
			alert(val);
		}
		,dataFilter:function(searchVal){
			console.log('dataFilter with:'+searchVal);
			return [
			{
				name:'哈哈哈，我是filter'
				,sn:'show:哈哈哈，我是filter'
			}
			,{
				name:'123'
				,sn:'show:123'
			}
			]
		}
		,dataSource:[{id:12,name:12,sn:'show:12'}
		,{id:13,name:13,sn:'show:13'}
		,{id:'fsa',name:'fsa',sn:'show:fsa'}
		,{id:13,name:'abcdefg',sn:'show:abcdefg'}
		,{id:13,name:'aaaa',sn:'show:aaaa'}
		,{id:13,name:'bbbb',sn:'show:bbbb'}
		,{id:13,name:'cccc',sn:'show:cccc'}
		,{id:13,name:'dddd',sn:'show:dddd'}
		,{id:13,name:'请问我确认为',sn:'show:请问我确认为'}
		,{id:13,name:'请问',sn:'show:请问'}
		,{id:13,name:'我要打',sn:'show:我要打'}
		,{id:13,name:'909090909090',sn:'show:909090909090'}
		]
	});
	// sb.refresh();
	var sb = SearchBox({
		target:$('input')
		,dropDownBtn:true
		,searchBtn:true
		,onSelect:function(keyword, data){
			if(data){
				alert(data.name);
				alert(data.sn);
			}
			alert(keyword);
		}
		// ,dataFilter:function(keyword){
		// 	console.log('dataFilter with:'+keyword);
		// 	return [
		// 	{
		// 		name:'哈哈哈，我是filter'
		// 		,sn:'show:哈哈哈，我是filter'
		// 	}
		// 	,{
		// 		name:'123'
		// 		,sn:'show:123'
		// 	}
		// 	]
		// }
		,dataSource:[{id:12,name:12,sn:'show:12'}
		,{id:13,name:13,sn:'show:13'}
		,{id:'fsa',name:'fsa',sn:'show:fsa'}
		,{id:13,name:'abcdefg',sn:'show:abcdefg'}
		,{id:13,name:'aaaa',sn:'show:aaaa'}
		,{id:13,name:'bbbb',sn:'show:bbbb'}
		,{id:13,name:'cccc',sn:'show:cccc'}
		,{id:13,name:'dddd',sn:'show:dddd'}
		,{id:13,name:'请问我确认为',sn:'show:请问我确认为'}
		,{id:13,name:'请问',sn:'show:请问'}
		,{id:13,name:'我要打',sn:'show:我要打'}
		,{id:13,name:'909090909090',sn:'show:909090909090'}
		]
	});
	// sb.refresh();
</script>
</html>